#include "err.hpp"
#include "sock.hpp"
#include <string>
#include <cstring>
#include <functional>
#include <poll.h>
#define arrsock_num 1024

namespace zxf
{

    class pool_server
    {
    public:
        using func_t = std::function<std::string(std::string &)>;
        pool_server(uint16_t port) : _port(port), _listensock(-1)
        {
        }
        ~pool_server()
        {
            if (_listensock >= 0)
            {
                close(_listensock);
            }
            if (_fds)
            {
                delete[] _fds;
            }
        }
        void initarrsock()
        {
            for (int i = 0; i < arrsock_num; i++)
            {
                _fds[i].fd = -1;
            }
            logMessage(NORMAL, "initarrsock success !!!");
        }

        void initServer()
        {
            _listensock = Sock::Socket();
            Sock::Bind(_listensock, _port);
            Sock::Listen(_listensock);
            _fds = new struct pollfd[arrsock_num];
            initarrsock();
            _fds[0].fd = _listensock;
            _fds[0].events = POLLIN; // 只关心读事件
        }

        void ListenHeader()
        {
            int fd = Sock::Accept(_listensock, nullptr, nullptr);
            int i = 0;
            for (i = 0; i < arrsock_num; i++)
            {
                if (_fds[i].fd == -1)
                {
                    _fds[i].fd = fd;
                    _fds[i].events = POLLIN;
                    break;
                }
            }
            if (i == arrsock_num)
            {
                logMessage(WARNING, " select full !!!");
            }
        }
        void CommonHeader(int fd, int pos)
        {
            logMessage(DEBUG, "CommonHeader in !!");
            char buf[1024];
            int ret = recv(fd, buf, 1023, 0);
            if (ret < 0)
            {
                // 读取出错了
                close(fd);
                _fds[pos].fd = -1;
                logMessage(ERROR, "recv err : %s", strerror(errno));
                return;
            }
            else if (ret == 0)
            {
                // 客户端退出
                close(fd);
                _fds[pos].fd = -1;
                logMessage(NORMAL, "client quit");
                return;
            }
            else
            {
                buf[ret] = 0;
                std::string request = buf;
                std::cout << "读取到: " << request << std::endl;
                const std::string response = _func(request);
                write(fd, response.c_str(), response.size());
            }
        }

        void Eventheader()
        {
            for (int i = 0; i < arrsock_num; i++)
            {
                if (_fds[i].fd == -1)  
                {
                    continue;
                }

                if (_fds[i].fd == _listensock && _fds[i].revents & POLLIN)
                {
                    ListenHeader();
                }
                if (_fds[i].fd != _listensock && _fds[i].revents & POLLIN)
                {
                    CommonHeader(_fds[i].fd, i);
                }
            }
        }

        void start(func_t func)
        {
            _func = func;

            for (;;)
            {
                int timeout = 3000; // 单位是毫秒
                int ret = poll(_fds, arrsock_num, timeout);
                // 注意read_fds是一个输入输出型的参数,输入要关心的文件描述符, 输出就绪的文件描述符.
                if (ret == -1)
                {
                    // err
                    logMessage(FATAL, "poll err !! errno: %d  err: %s", errno, strerror(errno));
                    exit(SELECT_ERR);
                }
                else if (ret == 0)
                {
                    logMessage(NORMAL, "timeout !!! ");
                    continue;
                }
                else
                {
                    // 有文件描述符就绪了
                    logMessage(NORMAL, "have event ready!");
                    Eventheader();
                }
            }
        }

    private:
        uint16_t _port;
        int _listensock;
        struct pollfd *_fds; // 所有要关心的fd
        func_t _func;
    };

}